package com.lindroy.androidplayer.viewmodels

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.map
import androidx.lifecycle.viewModelScope
import androidx.paging.CombinedLoadStates
import androidx.paging.LoadState
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.elvishew.xlog.XLog
import com.lindroy.androidplayer.interfaces.ILayoutState
import com.lindroy.androidplayer.logic.network.base.http.EmptyDataException
import com.lindroy.androidplayer.logic.network.base.http.NotLoginException
import com.lindroy.androidplayer.logic.network.enums.LayoutState
import com.lindroy.androidplayer.utils.SingleLiveEvent
import com.lindroy.androidplayer.utils.isTrue
import com.lindroy.androidplayer.utils.mapSingle
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import java.net.UnknownHostException

/**
 * @author Lin
 * @date 2022/1/19
 * @function
 */
open class PageViewModel : ViewModel(), ILayoutState {

    override val layoutStateLiveData: SingleLiveEvent<Int> = SingleLiveEvent()

    private val _refreshAction = MutableLiveData<Unit>()

    private val isRefreshingLiveData = MutableLiveData<Boolean>()

    val isRefreshing = isRefreshingLiveData.mapSingle { it }

    val refreshListener = SwipeRefreshLayout.OnRefreshListener {
        isRefreshingLiveData.postValue(true)
        _refreshAction.postValue(Unit)
    }

    val refreshLiveData = _refreshAction.map {
        _refreshAction.value
    }

    fun setLayoutStateFlow(stateFlow: Flow<CombinedLoadStates>) {
        viewModelScope.launch {
            //下拉刷新会先走 LoadState.NotLoading，所以需要先判断一下是否已经加载过数据，再将 isRefresh 设为 false
            var hasLoadData = false
            stateFlow.collect { state ->

                val layoutState = when (state.refresh) {
                    is LoadState.Loading -> {
                        hasLoadData = true
                        if (isRefreshing.value.isTrue) {
                            LayoutState.REFRESH
                        } else {
                            LayoutState.LOADING
                        }
                    }
                    is LoadState.NotLoading -> LayoutState.CONTENT
                    is LoadState.Error -> {
                        XLog.e((state.refresh as LoadState.Error).error)
                        when ((state.refresh as LoadState.Error).error) {
                            is UnknownHostException -> LayoutState.NO_NETWORK
                            is NotLoginException -> LayoutState.NOT_LOGIN
                            is EmptyDataException -> LayoutState.EMPTY
                            else -> LayoutState.SERVER_ERROR

                        }
                    }
                    else -> LayoutState.CONTENT
                }
                layoutStateLiveData.postValue(layoutState)
                if (hasLoadData && layoutState != LayoutState.LOADING) {
                    hasLoadData = false
                    isRefreshingLiveData.postValue(false)
                }
            }
        }
    }
}